package com.qudian.pay.log.aop;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.List;
import java.util.Map;
import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.qudian.pay.core.aop.BaseInterceptor;
import com.qudian.pay.core.utils.AnnotatedUtils;
import com.qudian.pay.core.utils.ReflectionUtils;
import com.qudian.pay.log.annotation.MethodMonitor;
import com.qudian.pay.log.annotation.ParamMonitor;
import com.qudian.pay.log.bo.MonitorBo;

/**
 * @Description: 服务摘要监控(异常方法、异常原因、时间、备注)
 * @ClassName: MonitorInterepter
 * @author gaoxiang
 * @date 2016年11月7日 下午4:01:33
 */
public class MonitorInterepter extends BaseInterceptor {
	
	private final static Logger logger = LoggerFactory.getLogger("monitor");
	
	/**
	 * @Fields sysGroup : 系统属组
	 */ 
	private String sysGroup;
	
	/**
	 * @Fields sysName : 系统名称
	 */ 
	private String sysName;
	
	@Override
	public Object bizInvoke(MethodInvocation invocation) throws Throwable {
		MethodMonitor methodMonitor = AnnotatedUtils.getAnnotated(MethodMonitor.class, invocation);
		if(methodMonitor != null) {
			MonitorBo monitorBo = new MonitorBo();
			monitorBo.setSysGroup(sysGroup);
			monitorBo.setSysName(sysName);
			monitorBo.setBusiCode(methodMonitor.name());
			Map<String,String> monitorData = getMethodParameterAnnotation(invocation);
			if(!monitorData.isEmpty()) {
				for(String name : monitorData.keySet()) {
					String value = monitorData.get(name);
					monitorBo.setName(name);
					monitorBo.setValue(value);
					logger.info(JSON.toJSONString(monitorBo));
				}
			}
		}
		try {
			return invocation.proceed();
		} catch (Throwable e) {
			throw e;
		}
	}
	
	public void setSysGroup(String sysGroup) {
		this.sysGroup = sysGroup;
	}
	
	public void setSysName(String sysName) {
		this.sysName = sysName;
	}
	
	public static Map<String,String> getMethodParameterAnnotation(MethodInvocation invocation) throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException {
		Map<String,String> map = Maps.newHashMap();
		Method method = invocation.getMethod();
		Object[] arguments = invocation.getArguments();
		Parameter[] parameters = method.getParameters();
		for(int i = 0;i<parameters.length;i++) {
			Object object = arguments[i];
			//首先获取入参上的监控注解
			ParamMonitor paramMonitor = parameters[i].getAnnotation(ParamMonitor.class);
			if(paramMonitor != null) {
				map.put(paramMonitor.name(), object == null?"":object.toString());
			}
			//接着获取入参实体里的属性监控注解
			String typeName = parameters[i].getParameterizedType().getTypeName();
			Class<?> forName = Class.forName(typeName);
			List<Field> allDeclaredField = ReflectionUtils.getAllDeclaredField(forName);
			for(Field field : allDeclaredField) {
				field.setAccessible(true);
				ParamMonitor annotation = field.getAnnotation(ParamMonitor.class);
				if(annotation != null) {
					Object object2 = field.get(object);
					map.put(annotation.name(), object2 ==null ? "":object2.toString());
				}
			}
		}
		return map;
	}
	
}
